contents
자바에서 메서드 레퍼런스(method reference) 는 단일 메서드만 실행하는 람다 표현식을 더 간결하고 가독성 좋게 표현하는 단축 문법입니다. 이는 자바 8에서 도입된 기능으로, 메서드를 호출 () 하지 않고 그 이름으로 참조할 수 있게 해줍니다.
마치 메서드에 대한 직접적인 포인터처럼 생각할 수 있으며, 이 포인터를 함수형 인터페이스가 필요한 곳에 전달하여 사용할 수 있습니다.
메서드 레퍼런스가 해결하는 문제: 람다의 장황함
메서드 레퍼런스는 간단한 람다 표현식의 상용구 코드를 줄여 코드 가독성을 향상시키기 위해 만들어졌습니다.
문자열 리스트가 있고 각 문자열을 출력하는 흔한 시나리오를 생각해 봅시다.
람다 표현식 사용:
List names = List.of("Alice", "Bob", "Charlie");
names.forEach(s -> System.out.println(s));
이 람다, s -> System.out.println(s)는 간단하지만 약간 불필요한 부분이 있습니다. 파라미터 s를 받아서 바로 System.out.println 메서드에 전달하는 역할만 합니다. 즉, 파라미터 s는 단지 전달을 위해 존재합니다.
메서드 레퍼런스 사용:
메서드 레퍼런스는 이를 아름답게 정리합니다.
List names = List.of("Alice", "Bob", "Charlie");
names.forEach(System.out::println);
이 코드는 정확히 동일한 작업을 수행하지만 더 간결하고 표현력이 풍부합니다. "각 이름에 대해, System.out 객체의 println 메서드를 호출하라"는 의도를 명확하게 나타냅니다.
문법 및 요구사항 📜
메서드 레퍼런스는 :: (이중 콜론) 연산자를 사용합니다.
가장 기본적인 요구사항은 메서드 레퍼런스가 대상 함수형 인터페이스의 추상 메서드와 호환되어야 한다는 것입니다. 즉, 참조되는 메서드의 파라미터 타입과 반환 타입이 함수형 인터페이스가 기대하는 것과 일치해야 합니다.
네 가지 유형의 메서드 레퍼런스
메서드 레퍼런스에는 각각 고유한 문법을 가진 네 가지 종류가 있습니다.
1. 정적 메서드에 대한 레퍼런스
정적 메서드를 호출하고 싶을 때 사용됩니다.
-
문법:
클래스이름::정적메서드이름 -
예시:
String리스트를Integer리스트로 변환하기. 람다:ListnumbersAsStrings = List.of("10", "20", "30"); List numbers = numbersAsStrings.stream() .map(s -> Integer.parseInt(s)) .toList(); 메서드 레퍼런스:
ListnumbersAsStrings = List.of("10", "20", "30"); List numbers = numbersAsStrings.stream() .map(Integer::parseInt) // Integer 클래스의 정적 메서드인 parseInt 호출 .toList();
2. 특정 객체의 인스턴스 메서드에 대한 레퍼런스
특정, 기존 인스턴스의 메서드를 호출하고 싶을 때 사용됩니다.
-
문법:
인스턴스참조::인스턴스메서드이름 -
예시: 특정
System.out인스턴스를 사용하여 각 문자열 출력하기. 람다:Listnames = List.of("Alice", "Bob"); names.forEach(s -> System.out.println(s)); 메서드 레퍼런스:
Listnames = List.of("Alice", "Bob"); // `System.out`이 바로 그 특정 인스턴스 names.forEach(System.out::println);
3. 특정 타입의 임의의 객체에 대한 인스턴스 메서드 레퍼런스
가장 일반적이고 강력한 유형이지만, 가장 미묘한 차이가 있습니다. 람다의 첫 번째 파라미터가 메서드를 호출하는 객체일 때 사용됩니다.
-
문법:
클래스이름::인스턴스메서드이름 -
예시 1: 리스트에 있는 각 문자열의 길이 구하기. 람다:
Listnames = List.of("Alice", "Bob", "Charlie"); List lengths = names.stream() .map(s -> s.length()) // 람다의 파라미터 `s`가 인스턴스 자체가 됨 .toList(); 여기서 람다는
String s를 받아서 그s객체의length()메서드를 호출합니다.메서드 레퍼런스:
Listnames = List.of("Alice", "Bob", "Charlie"); List lengths = names.stream() .map(String::length) // 스트림의 각 요소에 대해 length() 메서드 호출 .toList(); -
예시 2: 대소문자를 무시하고 문자열 정렬하기.
Comparator인터페이스의 메서드는compare(s1, s2)입니다. 람다:String[] names = {"bob", "Alice", "charlie"}; Arrays.sort(names, (s1, s2) -> s1.compareToIgnoreCase(s2));여기서 첫 번째 파라미터
s1이 인스턴스가 되고, 두 번째 파라미터s2가 메서드에 전달됩니다.**메서드 레퍼런스:
String[] names = {"bob", "Alice", "charlie"}; Arrays.sort(names, String::compareToIgnoreCase);
4. 생성자에 대한 레퍼런스
새 객체를 생성하는 데 사용됩니다.
-
문법:
클래스이름::new -
예시: 이름 리스트로부터
Person객체 리스트 생성하기. **람다:Listnames = List.of("Alice", "Bob"); List people = names.stream() .map(name -> new Person(name)) .toList(); 메서드 레퍼런스:
Listnames = List.of("Alice", "Bob"); List people = names.stream() .map(Person::new) // Person 생성자 호출 .toList();
요약하자면, 메서드 레퍼런스는 불필요한 람다 문법을 제거함으로써 함수형 스타일의 코드를 더 깔끔하고 간결하며 표현력 있게 만들어주는 현대 자바의 강력한 기능입니다.
references